package com.huanyu.backend.study.concurrency.thread;

import java.util.concurrent.TimeUnit;

/**
 * 线程基本操作的例子
 * wait
 * 阻塞挂起当前线程，释放锁
 * notify
 * 线程被唤醒后，需要重新竞争锁，获取到锁才可以返回
 * notifyAll
 * 上面三个操作获取到锁才能调用
 *
 * join
 * 等待线程执行终止
 * 当前线程会被阻塞
 * 可以通过interrupt方法中断当前线程
 * #直接在main线程中调用join会一直阻塞#
 *
 * sleep
 * 让线程睡眠
 * 睡眠期间不参与CPU的调度
 * 不释放锁
 *
 * yield
 * 让出CPU执行权
 * 只是让出剩余的时间片
 * 没有阻塞挂起
 * 处于就绪状态
 *
 * interrupt
 * 中断线程
 * 线程实际并没有被中断，它会继续往下执行
 * java的中断并不是真正的中断线程，而只设置标志位（中断位）来通知用户
 * 如果因为wait系列函数，join方法或者sleep方法被阻塞挂起，会抛出InterruptedException异常而返回
 * 一旦方法抛出InterruptedException，当前调用该方法的线程的中断状态就会被jvm自动清除
 * 因为如果你捕获到中断异常，说明当前线程已经被中断，不需要继续保持中断位
 *
 * isInterrupted
 * 检测当前线程是否被中断，如果是返回true，否则返回false
 *
 * interrupted
 * 获取当前调用线程的中断标志，如果线程被中断，会清除中断标志
 */
public class ThreadOperationExample {
    private static final Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        // join
        joinOperation();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // sleep
        sleepOperation();

        // yield
        yieldOperation();

        // interrupt
        interruptOperation();
    }

    public static void interruptOperation() throws InterruptedException {
        Thread interruptThread = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                System.out.println("interruptThread线程被中断，继续往下执行");
            }
            // false
            System.out.println("InterruptedException返回之后 interruptThread线程的中断标志: " + Thread.currentThread().isInterrupted());
            System.out.println("interruptThread线程继续执行");
        });
        interruptThread.start();

        TimeUnit.SECONDS.sleep(1);
        // false
        System.out.println("interruptThread线程中断之前的中断标志: " + interruptThread.isInterrupted());
        interruptThread.interrupt();
        // true， 如果没有中断之前的isInterrupted方法调用，也会返回false(有点奇怪)
        System.out.println("interruptThread线程中断之前的中断标志: " + interruptThread.isInterrupted());
    }

    public static void yieldOperation() {
        Thread otherThread = new Thread(() -> System.out.println("other线程执行"));

        Thread yieldThread = new Thread(() -> {
            synchronized (object) {
                Thread.yield();
                otherThread.start();
                System.out.println("线程调用yield之后，别的线程有可能会执行");
            }
        });

        yieldThread.start();

    }

    public static void sleepOperation() {
        Thread sleepThread = new Thread(() -> {
            synchronized (object) {
                System.out.println("sleepThread获取到锁");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("sleepThread睡眠完成才会释放锁，其他线程才能获取锁");
            }
        });

        sleepThread.start();

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (object) {
            System.out.println("当前线程获取到锁");
        }
    }

    public static void joinOperation() {
        Thread longTimeRunThread = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("longTimeRunThread线程执行完成");
        });
        longTimeRunThread.start();

        Thread waitingExecThread = new Thread(() -> {
            try {
                longTimeRunThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("等待longTimeRunThread线程执行完成");
        });

        waitingExecThread.start();
    }
}
